﻿// <copyright file="FoseVersion.cs" company="SingularityShift">
// Copyright (c) 2009 SingularityShift.com
// </copyright>
// <author>Ben McClure</author>
// <email>ben@singularityshift.com</email>
// <date>2009-08-14</date>
// <summary>A struct representing an FOSE version number</summary>
namespace GameLib.Games.Fallout3
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// A structure identifying a FOSE (Fallout 3 Script Extender) version number
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Fose", Justification = "FOSE is a valid Fallout 3 term")]
    public struct FoseVersion : IEquatable<FoseVersion>
    {
        /// <summary>
        /// The major part of the version number
        /// </summary>
        private readonly int major;
        
        /// <summary>
        /// The minor part of the version number
        /// </summary>
        private readonly int minor;
        
        /// <summary>
        /// The build part of the version number
        /// </summary>
        private readonly int build;
        
        /// <summary>
        /// The revision part of the version number
        /// </summary>
        private readonly int revision;
        
        /// <summary>
        /// Initializes a new instance of the FoseVersion struct.
        /// </summary>
        /// <param name="major">The major part of the version number</param>
        /// <param name="minor">The minor part of the version number</param>
        /// <param name="build">The build part of the version number</param>
        /// <param name="revision">The revision part of the version number</param>
        public FoseVersion(int major, int minor, int build, int revision)
        {
            this.major = major;
            this.minor = minor;
            this.build = build;
            this.revision = revision;
        }
        
        /// <summary>
        /// Gets the first in the sequence, this is the major version number.
        /// </summary>
        public int Major
        {
            get
            {
                return this.major;
            }
        }

        /// <summary>
        /// Gets the second in the sequence, this is the minor version number.
        /// </summary>
        public int Minor
        {
            get
            {
                return this.minor;
            }
        }

        /// <summary>
        /// Gets the third in the sequence, this is the build number (we think)
        /// </summary>
        public int Build
        {
            get
            {
                return this.build;
            }
        }

        /// <summary>
        /// Gets the fourth in the sequence, this is the revision number (we think)
        /// </summary>
        public int Revision
        {
            get
            {
                return this.revision;
            }
        }
        
        /// <summary>
        /// Implements a more efficient == operator for this struct
        /// </summary>
        /// <param name="version1">The first version to compare</param>
        /// <param name="version2">The second version to compare</param>
        /// <returns>A value indicating whether both versions are equal</returns>
        public static bool operator ==(FoseVersion version1, FoseVersion version2)
        {
            return version1.Equals(version2);
        }
        
        /// <summary>
        /// Implements a more efficient != operator for this struct
        /// </summary>
        /// <param name="version1">The first version to compare</param>
        /// <param name="version2">The second version to compare</param>
        /// <returns>A value indicating whether both versions are not equal</returns>
        public static bool operator !=(FoseVersion version1, FoseVersion version2)
        {
            return !version1.Equals(version2);
        }
        
        /// <summary>
        /// Gets a unique hash code for this struct.
        /// </summary>
        /// <returns>An integer specifying the hash code</returns>
        public override int GetHashCode()
        {
            return this.major ^ this.minor ^ this.build ^ this.revision;
        }
        
        /// <summary>
        /// Overrides the less-efficient Equals method with a custom one.
        /// </summary>
        /// <param name="obj">The other object to check for equality against.</param>
        /// <returns>A value indicating whether both objects are equal.</returns>
        public override bool Equals(object obj)
        {
            if (!(obj is FoseVersion))
            {
                return false;
            }
            
            return this.Equals((FoseVersion)obj);
        }
        
        /// <summary>
        /// Implements a more efficient version of Equals for this struct
        /// </summary>
        /// <param name="other">The other version to check for equality against</param>
        /// <returns>A value indicating whether both FoseVersion objects are equal.</returns>
        public bool Equals(FoseVersion other)
        {
            if (this.Major != other.Major)
            {
                return false;
            }
            
            if (this.Minor != other.Minor)
            {
                return false;
            }
            
            if (this.Build != other.Build)
            {
                return false;
            }
            
            if (this.Revision != other.Revision)
            {
                return false;
            }
            
            return true;
        }
    }
}
